home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / scan.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  10KB  |  452 lines

  1. /*
  2.  * @(#)scan.c    1.5  10/6/87
  3.  */
  4. #include "assert.h"
  5. #include "nodes.h"
  6. #include "tokens.h"
  7. #include "system.h"
  8. #include "MyParser.h"
  9. #include "keyword.h"
  10. #include "error.h"
  11. Token currentToken, nextToken;
  12. NodePtr currentTokenValue, nextTokenValue;
  13. extern NodePtr yylval;
  14.  
  15. #define TNO -1
  16.  
  17. FILE *inputFile;
  18. char *currentFileName = NULL;
  19. int currentLineNumber = 1;
  20. int nextLineNumber = 0;
  21. int needIncLineNumber = 1;
  22.  
  23. static TokenBuffer nextTokenBuffer;
  24.  
  25. static int
  26.   ScanIllegal(), ScanLetter(), ScanColon(), ScanLparen(), 
  27.   ScanRparen(), ScanDigit(), ScanDot(), ScanStringquote(),
  28.   ScanCharquote(), ScanComma(), ScanComment(), ScanOperator();
  29.   ScanLsquare(), ScanRsquare(),
  30.   ScanLcurly(), ScanRcurly(), ScanDollar(),
  31.   ScanEof(), ScanWhite(), ScanNL();
  32.  
  33. static void extend(tb)
  34. register TokenBufferPtr tb;
  35. {
  36.   register char *newBuffer;
  37.   register int currentLength;
  38.   currentLength = tb->bufferEnd - tb->buffer;
  39.  
  40.   newBuffer = (char *) malloc((unsigned)2 * currentLength);
  41.   bcopy(tb->buffer, newBuffer, currentLength);
  42.   free(tb->buffer);
  43.   tb->buffer = newBuffer;
  44.   tb->fillPtr = tb->buffer + currentLength;
  45.   tb->bufferEnd = tb->buffer + 2 * currentLength;
  46.   currentLength = 2 * currentLength;
  47. }
  48.  
  49. #define collect(tb, c) \
  50.   if ((tb)->fillPtr >= (tb)->bufferEnd) { \
  51.     extend(tb); \
  52.   } \
  53.   *(tb)->fillPtr++ = c;
  54.  
  55. char *strdup(S)
  56. char *S;
  57. {
  58.   register char *str;
  59.   register int length;
  60.   length = strlen(S) + 1;
  61.   str = (char *) malloc ((unsigned)length);
  62.   bcopy(S, str, length);
  63.   return(str);
  64. }
  65.  
  66. /* This is the scanner which presents a token stream to its caller. */
  67.  
  68. static int nextChar = ' ';
  69. TokenBuffer lineBuffer;
  70. int currentPosition = 0;
  71. static int positionInLine = -1;
  72.  
  73. static void readLine()
  74. {
  75.   register int c;
  76.   lineBuffer.fillPtr = lineBuffer.buffer;
  77.   positionInLine = -1;
  78.   do {
  79.     c = getc(inputFile);
  80.     collect(&lineBuffer, c);
  81.   } while (c != EOF && c != '\n');
  82.   collect(&lineBuffer, '\0');
  83. }
  84.  
  85. #define MgetNextChar() {\
  86.   register int c; \
  87.   if (needIncLineNumber) { \
  88.     nextLineNumber++; \
  89.     readLine(); \
  90.   } \
  91.   c = lineBuffer.buffer[++positionInLine]; \
  92.   if (c == EOF) nextChar = -1; \
  93.   else { \
  94.     nextChar = c; \
  95.     if (c & 0xffffff80) ScanIllegal(); \
  96.     needIncLineNumber = (c == '\n'); \
  97.   } \
  98. }
  99.  
  100. void getNextChar()
  101. {
  102.   MgetNextChar();
  103. }
  104.  
  105. typedef int CharClasses;
  106. /*
  107. * We are changing things so that operation names can be made up of strange
  108. * characters.  Basically these things are now treated like identifiers, with
  109. * keywords and all.  The legal operator characters are =!><|&+-/*#@?^~.
  110. */
  111. #define CILLEGAL 0
  112. #define CLETTER 1
  113. #define CCOLON 2
  114. #define CLPAREN 3
  115. #define CRPAREN 4
  116. #define CDIGIT 5
  117. #define CDOT 6
  118. #define CSTRINGQUOTE 7
  119. #define CCHARQUOTE 8
  120. #define CCOMMA 9
  121. #define CCOMMENT 10
  122. #define COPERATOR 11
  123. #define CLSQUARE 12
  124. #define CRSQUARE 13
  125. #define CLCURLY 14
  126. #define CRCURLY 15
  127. #define CDOLLAR 16
  128. #define CEOF 17
  129. #define CWHITE 18
  130. #define CNL 19
  131.  
  132. /* This must come right before CharClasses since we use it to detect eof. */
  133. static CharClasses junk[1] = { CEOF };
  134. /* This has to be initialized */
  135. static CharClasses charClass[128] = {
  136. CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,
  137. CILLEGAL,CWHITE,CNL,CILLEGAL,CWHITE,CWHITE,CILLEGAL,CILLEGAL,
  138. CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,
  139. CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,CILLEGAL,
  140. CWHITE,COPERATOR,CSTRINGQUOTE,COPERATOR,CDOLLAR,CCOMMENT,COPERATOR,CCHARQUOTE,
  141. CLPAREN,CRPAREN,COPERATOR,COPERATOR,CCOMMA,COPERATOR,CDOT,COPERATOR,
  142. CDIGIT,CDIGIT,CDIGIT,CDIGIT,CDIGIT,CDIGIT,CDIGIT,CDIGIT,
  143. CDIGIT,CDIGIT,CCOLON,CILLEGAL,COPERATOR,COPERATOR,COPERATOR,COPERATOR,
  144. COPERATOR,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,
  145. CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,
  146. CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,
  147. CLETTER,CLETTER,CLETTER,CLSQUARE,CILLEGAL,CRSQUARE,COPERATOR,CLETTER,
  148. CILLEGAL,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,
  149. CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,
  150. CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,CLETTER,
  151. CLETTER,CLETTER,CLETTER,CLCURLY,COPERATOR,CRCURLY,COPERATOR,CILLEGAL
  152. };
  153.  
  154. static int (*charRoutines[])() = {
  155.   /* CILLEGAL */    ScanIllegal,
  156.   /* CLETTER */    ScanLetter,
  157.   /* CCOLON */    ScanColon,
  158.   /* CLPAREN */    ScanLparen,
  159.   /* CRPAREN */    ScanRparen,
  160.   /* CDIGIT */    ScanDigit,
  161.   /* CDOT */        ScanDot,
  162.   /* CSTRINGQUOTE */    ScanStringquote,
  163.   /* CCHARQUOTE */    ScanCharquote,
  164.   /* CCOMMA */    ScanComma,
  165.   /* CCOMMENT */    ScanComment,
  166.   /* COPERATOR */    ScanOperator,
  167.   /* CLSQUARE */    ScanLsquare,
  168.   /* CRSQUARE */    ScanRsquare,
  169.   /* CLCURLY */    ScanLcurly,
  170.   /* CRCURLY */    ScanRcurly,
  171.   /* CDOLLAR */    ScanDollar,
  172.   /* CEOF */        ScanEof,
  173.   /* CWHITE */    ScanWhite,
  174.   /* CNL */        ScanNL };
  175.  
  176. void Scanner_Accept()
  177. {
  178.   currentToken = nextToken;
  179.   currentTokenValue = nextTokenValue;
  180.   currentLineNumber = nextLineNumber;
  181.   nextTokenBuffer.fillPtr = nextTokenBuffer.buffer;
  182.   nextTokenValue = (NodePtr) -1;
  183.   scan();
  184. }
  185.  
  186. static int ScanIllegal()
  187. {
  188.   IllegalCharacter(nextChar);
  189.   getNextChar();
  190. }
  191.  
  192. static int ScanLetter()
  193. {
  194.   register Ident id;
  195.   register int cc;
  196.   do {
  197.     collect(&nextTokenBuffer, nextChar);
  198.     getNextChar();
  199.     cc = charClass[nextChar];
  200.   } while (cc == CLETTER || cc == CDIGIT);
  201.   collect(&nextTokenBuffer, '\0');
  202.   id = Ident_Lookup(nextTokenBuffer.buffer, 
  203.       nextTokenBuffer.fillPtr - nextTokenBuffer.buffer - 1);
  204.   if (id <= lastKeywordIdent) {
  205.     nextToken = firstKeyword + id;
  206.   } else {
  207.     nextToken = TIDENTIFIER;
  208.     nextTokenValue = NewNode(T_IDENT);
  209.     nextTokenValue->b.ident.ident = id;
  210.   }
  211. }
  212.  
  213. static int ScanOperator()
  214. {
  215.   register Ident id;
  216.   register int cc;
  217.   do {
  218.     collect(&nextTokenBuffer, nextChar);
  219.     getNextChar();
  220.     cc = charClass[nextChar];
  221.   } while (cc == COPERATOR);
  222.   collect(&nextTokenBuffer, '\0');
  223.   id = Ident_Lookup(nextTokenBuffer.buffer, 
  224.       nextTokenBuffer.fillPtr - nextTokenBuffer.buffer - 1);
  225.   if (id <= lastKeywordIdent) {
  226.     nextToken = firstKeyword + id;
  227.   } else {
  228.     nextToken = TOPERATOR;
  229.     nextTokenValue = NewNode(T_IDENT);
  230.     nextTokenValue->b.ident.ident = id;
  231.   }
  232. }
  233.  
  234. static int ScanColon()
  235. {
  236.   getNextChar();
  237.   if (nextChar == '=') {
  238.     getNextChar();
  239.     nextToken = TSUGARASSIGN;
  240.   } else {
  241.     nextToken = TCOLON;
  242.   }
  243. }
  244.  
  245. static int ScanLparen()
  246. {
  247.   getNextChar();
  248.   nextToken = TLPAREN;
  249. }
  250. static int ScanRparen()
  251. {
  252.   getNextChar();
  253.   nextToken = TRPAREN;
  254. }
  255. static int ScanDigit()
  256. {
  257.   do {
  258.     collect(&nextTokenBuffer, nextChar);
  259.     getNextChar();
  260.   } while (charClass[nextChar] == CDIGIT);
  261.   if (nextChar == '.') {
  262.     do {
  263.       collect(&nextTokenBuffer, nextChar);
  264.       getNextChar();
  265.     } while (charClass[nextChar] == CDIGIT);
  266.     nextToken = TREALLITERAL;
  267.   } else {
  268.     nextToken = TINTEGERLITERAL;
  269.   }
  270.   collect(&nextTokenBuffer, '\0');
  271.   nextTokenValue = NewNode(T_STRING);
  272.   nextTokenValue->b.string.string = strdup(nextTokenBuffer.buffer);
  273. }
  274. static int ScanDot()
  275. {
  276.   getNextChar();
  277.   nextToken = TDOT;
  278. }
  279. static int ScanComma()
  280. {
  281.   getNextChar();
  282.   nextToken = TCOMMA;
  283. }
  284. static int ScanComment()
  285. {
  286.   do {
  287.     getNextChar();
  288.   } while (charClass[nextChar] != CNL);
  289. }
  290. static int ScanLsquare()
  291. {
  292.   getNextChar();
  293.   nextToken = TLSQUARE;
  294. }
  295. static int ScanRsquare()
  296. {
  297.   getNextChar();
  298.   nextToken = TRSQUARE;
  299. }
  300. static int ScanLcurly()
  301. {
  302.   getNextChar();
  303.   nextToken = TLCURLY;
  304. }
  305. static int ScanRcurly()
  306. {
  307.   getNextChar();
  308.   nextToken = TRCURLY;
  309. }
  310. static int ScanDollar()
  311. {
  312.   getNextChar();
  313.   nextToken = TDOLLAR;
  314. }
  315. static int DoAChar()
  316. {
  317.   register char c = nextChar;
  318.   register int num = 0;
  319.   if (c == '\\') {
  320.     getNextChar();
  321.     if (nextChar == '^') {
  322.       getNextChar();
  323.       num = nextChar & 0x1f;
  324.       getNextChar();
  325.     } else if ('0' <= nextChar && nextChar <= '7') {
  326.       /* a C octal escape */
  327.       num = nextChar - '0';
  328.       getNextChar();
  329.       if ('0' <= nextChar && nextChar <= '7') {
  330.     num *= 8;
  331.     num += nextChar - '0';
  332.     getNextChar();
  333.     if ('0' <= nextChar && nextChar <= '7') {
  334.       num *= 8;
  335.       num += nextChar - '0';
  336.       getNextChar();
  337.     }
  338.       }
  339.     } else {
  340.       switch (nextChar) {
  341.     case 'n':
  342.       num = '\n';
  343.       break;
  344.     case 'b':
  345.       num = '\b';
  346.       break;
  347.     case 't':
  348.       num = '\t';
  349.       break;
  350.     case 'r':
  351.       num = '\r';
  352.       break;
  353.     case 'f':
  354.       num = '\f';
  355.       break;
  356.     default:
  357.       num = nextChar;
  358.       break;
  359.       }
  360.       getNextChar();
  361.     }
  362.   } else {
  363.     num = nextChar;
  364.     getNextChar();
  365.   }
  366.   return(num);
  367. }
  368. static int ScanStringquote()
  369. {
  370.   getNextChar();
  371.   while (1) {
  372.     if (nextChar == -1) {
  373.       UnexpectedEndOfFile();
  374.       break;
  375.     } else if (nextChar == '"') {
  376.       getNextChar();
  377.       break;
  378.     }
  379.     collect(&nextTokenBuffer, DoAChar());
  380.   }
  381.   collect(&nextTokenBuffer, '\0');
  382.   nextToken = TSTRINGLITERAL;
  383.   nextTokenValue = NewNode(T_STRING);
  384.   nextTokenValue->b.string.string = strdup(nextTokenBuffer.buffer);
  385. }
  386. static int ScanCharquote()
  387. {
  388.   getNextChar();
  389.   if (nextChar == -1) {
  390.     UnexpectedEndOfFile();
  391.   }
  392.   collect(&nextTokenBuffer, DoAChar());
  393.   if (nextChar != '\'') {
  394.     BeginSyntaxErrorMessage(1);
  395.     ErrorWrite("expected \"'\"");
  396.     EndErrorMessage();
  397.   }
  398.   getNextChar();
  399.   collect(&nextTokenBuffer, '\0');
  400.   nextToken = TCHARACTERLITERAL;
  401.   nextTokenValue = NewNode(T_STRING);
  402.   nextTokenValue->b.string.string = strdup(nextTokenBuffer.buffer);
  403. }
  404.  
  405. static int ScanEof()
  406. {
  407.   nextToken = TEOF;
  408. }
  409. static int ScanWhite()
  410. {
  411.   do {
  412.     getNextChar();
  413.   } while (charClass[nextChar] == CWHITE);
  414. }
  415.  
  416. static int ScanNL()
  417. {
  418.   getNextChar();
  419. }
  420.  
  421. /* This one scans until it finds the next token, leaving it in nextToken* */
  422.  
  423. scan()
  424. {
  425.   nextToken = TNO;
  426.   do {
  427.     currentPosition = positionInLine;
  428.     (*charRoutines[charClass[nextChar]])();
  429.   } while (nextToken == TNO);
  430.   if (nextTokenValue == (NodePtr) -1) nextTokenValue = (NodePtr) nextToken;
  431. }
  432.  
  433. void Scanner_Initialize()
  434. {
  435.   junk[0] = CEOF;
  436.   nextTokenBuffer.buffer = (char *) malloc(80);
  437.   nextTokenBuffer.bufferEnd = nextTokenBuffer.buffer + 80;
  438.   nextTokenBuffer.fillPtr = nextTokenBuffer.buffer;
  439.   lineBuffer.buffer = (char *) malloc(100);
  440.   lineBuffer.bufferEnd = lineBuffer.buffer + 100;
  441.   lineBuffer.fillPtr = lineBuffer.buffer;
  442.   Ident_Initialize();
  443.   Keyword_Initialize();
  444. }
  445.  
  446. int yylex()
  447. {
  448.   Scanner_Accept();
  449.   yylval = nextTokenValue;
  450.   return(nextToken);
  451. }
  452.